package com.dongqi.utils;

import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.xml.bind.*;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import java.io.*;
import java.lang.reflect.Field;

@Slf4j
public class XmlToModel {

    /**
     * xml文件配置转换为对对象
     *
     * @param data xml文件路径
     * @param load java对象.Class
     * @return java对象
     * @throws JAXBException
     * @throws IOException
     */
    public static <T> T xmlToObject(String data, Class<T> load) throws Exception {
        InputStream stream = new ByteArrayInputStream(data.getBytes("UTF-8"));
        JAXBContext context = JAXBContext.newInstance(load);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLEventReader someSource = factory.createXMLEventReader(stream);
        JAXBElement<T> userElement = unmarshaller.unmarshal(someSource, load);
        return userElement.getValue();
    }



    public static String toData(Object object) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(object.getClass());
        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.setProperty(Marshaller.JAXB_FRAGMENT, true);
        //这边要单独提取出来创建一个公共的对象，不然每次解析都会创建会造成内存泄漏
        m.setListener(marListener);
        StringWriter output = new StringWriter(2048);
        m.marshal(object, output);
        String data = output.toString();
        return data;
    }


    private static final Marshaller.Listener marListener = new Marshaller.Listener() {
        @Override
        public void beforeMarshal(Object source) {
            Field[] fields = source.getClass().getDeclaredFields();
            for (Field f : fields) {
                f.setAccessible(true);
                try {
                    //对象为空且类型为String时候设置空值
                    if (f.getType() == String.class && f.get(source) == null) {
                        f.set(source, "");
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    };


    public static org.dom4j.Element str2Document(String data) {
        InputStream xmlStream;
        Document doc;
        Element rootElement = null;
        try {
            xmlStream = new ByteArrayInputStream(data.getBytes("utf-8"));
            SAXReader reader = new SAXReader();
            doc = reader.read(xmlStream);
            rootElement = doc.getRootElement();
        } catch (UnsupportedEncodingException e) {
            log.error("String类型转Byte出错了", e);
        } catch (DocumentException e) {
            log.error("流转XmlDocument失败", e);
        }
        return rootElement;
    }
}
